<?php
/*
//cach su dung
$WKHT = new JimWkhtmltopdf();
$WKHT->set_config(array(
    'cmd' => 'tool\wkhtmltopdf\wkhtmltopdf.exe',
    'output' => 'tmp',
    'web' => 'http://codeigniter.com/user_guide/general/libraries.html',
    'page_size' => 'A4',//'Letter','A4'
    'file_name'=> 'MOCAA_'.time().'.pdf',
    'type'=>'savefile'//'savefile','download'
    )
);
$exportFile = $WKHT->render();
*/
class JimWkhtmltopdf {
    /**
     * Private use variables.
     */
    private $html='';
    private $cmd='';
    private $tmp='';
    private $pdf='';
    private $status='';
    private $orient='Portrait';
    private $size='A4';
    private $toc=false;
    private $copies=1;
    private $grayscale=false;
    private $title='';
    private $web;
    private $config=array();
    
    private $filename='';
    /**
     * Force the client to download PDF file when finish() is called.
     */
    public static $PDF_DOWNLOAD='D';
    /**
     * Returns the PDF file as a string when finish() is called.
     */
    public static $PDF_ASSTRING='S';

    /**
     * When possible, force the client to embed PDF file when finish() is called.
     */
    public static $PDF_EMBEDDED='I';
    
    /**
     * PDF file is saved into the server space when finish() is called. The path is returned.
     */
    public static $PDF_SAVEFILE='F';
    
    /**
     * PDF generated as landscape (vertical).
     */
    public static $PDF_PORTRAIT='Portrait';

    /**
     * PDF generated as landscape (horizontal).
     */
    public static $PDF_LANDSCAPE='Landscape';

    /**
     *     An instance of the CI super object.
     */
    private static $ci;
    
    private $success = true;

    /**
     * Constructor: initialize command line and reserve temporary file.
     */    
    public function __construct(){
        //self::$ci =& get_instance();
        
        //$this->cmd = 'C:\Program Files (x86)\wkhtmltopdf\wkhtmltopdf.exe';
        //$this->cmd = 'wkhtmltopdf\wkhtmltopdf.exe';

        //$GLOBALS['WKPDF_BASE_PATH'] = '';
        //$GLOBALS['WKPDF_BASE_PATH'] = self::$ci->config->item('base_url');
        //$GLOBALS['WKPDF_BASE_SITE'] = 'http://'.$_SERVER['SERVER_NAME'].'/';
    }
    
    public function set_config($data = array()){
        $this->config = $data;
        //$this->config['cmd'] = $data['cmd'];
        //$this->config['output'] = $data['output'];
        //$this->config['web'] = $data['web'];
    }
    
    public function get_filename(){
        if( !isset($this->config['cmd']) || !isset($this->config['output']) ){
            $this->success = false;
            exit;
        }
        $this->web = $this->config['web'];
        $this->cmd = $this->config['cmd'];
        $this->size = $this->config['page_size'];
        do {
            $filename = mt_rand();
            //$this->tmp = 'tmp/'.$filename.'.pdf';
            $this->tmp = $this->config['output'].'/'.$filename.'.pdf';
            $this->filename = $filename;
        } while(file_exists($this->tmp));
    }
    
    /**
     * Set orientation, use constants from this class.
     * By default orientation is portrait.
     * @param string $mode Use constants from this class.
     */
    public function set_orientation($mode){
        $this->orient=$mode;
    }
    /**
     * Set page/paper size.
     * By default page size is A4.
     * @param string $size Formal paper size (eg; A4, letter...)
     */
    public function set_page_size($size){
        $this->size=$size;
    }
    /**
     * Whether to automatically generate a TOC (table of contents) or not.
     * By default TOC is disabled.
     * @param boolean $enabled True use TOC, false disable TOC.
     */
    public function set_toc($enabled){
        $this->toc=$enabled;
    }
    /**
     * Set the number of copies to be printed.
     * By default it is one.
     * @param integer $count Number of page copies.
     */
    public function set_copies($count){
        $this->copies=$count;
    }
    /**
     * Whether to print in grayscale or not.
     * By default it is OFF.
     * @param boolean True to print in grayscale, false in full color.
     */
    public function set_grayscale($mode){
        $this->grayscale=$mode;
    }
    /**
     * Set PDF title. If empty, HTML <title> of first document is used.
     * By default it is empty.
     * @param string Title text.
     */
    public function set_title($text){
        $this->title=$text;
    }

    /**
     * Set web address.
     * @param string $url An absolute URL
     */
    public function set_web($url){
        $this->web =$url;
    }

    /**
     * Returns WKPDF print status.
     * @return string WPDF print status.
     */
    public function get_status(){
        return $this->status;
    }

    /**
     * Convert HTML to PDF.
     */
    public function render(){
        $this->get_filename();
        if (empty($this->web)) {
            //$this->web=$GLOBALS['WKPDF_BASE_SITE'].$GLOBALS['WKPDF_BASE_PATH'].'tmp/'.basename($this->tmp);
            $this->success = false;
            exit;
        }

        $job =    '"'.$this->cmd.'"'
        .(($this->copies>1)?' --copies '.$this->copies:'')                    // number of copies
        .' --orientation '.$this->orient                                    // orientation
        .' --page-size '.$this->size                                        // page size
        .' -B 12 -T 12 -L 12 -R 12'                                            // set a 12mm border / half an inch
        .' --dpi 100'
        //.' --load-error-handling ignore '
        .($this->toc?' --toc':'')                                            // table of contents
        .($this->grayscale?' --grayscale':'')                                // grayscale
        .(($this->title!='')?' --title "'.$this->title.'"':'')                // title
        .' '.$this->web .' '. $this->tmp . ' 2>&1';                                    // URL and file to write to

        if (shell_exec($job) == null) {
            $this->status='error';
        }
        $this->pdf=file_get_contents($this->tmp);
        //unlink($this->tmp);
        $file_path = '';
        switch( $this->config['type'] ){
            case 'download':
                header('Content-Description: File Transfer');
                header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
                header('Pragma: public');
                header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
                header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
                // force download dialog
                header('Content-Type: application/force-download');
                header('Content-Type: application/octet-stream', false);
                header('Content-Type: application/download', false);
                header('Content-Type: application/pdf', false);
                // use the Content-Disposition header to supply a recommended filename
                header('Content-Disposition: attachment; filename="'.basename( $this->config['file_name'] ).'";');
                header('Content-Transfer-Encoding: binary');
                header('Content-Length: '.strlen($this->pdf));
                
                echo $this->pdf;
                unlink($this->tmp);
            break;
            
            case 'savefile':
                if( $this->config['file_name'] != '' ){
                    rename($this->tmp, $this->config['output'].'/'.$this->config['file_name'].'.pdf');
                    $file_path = $this->config['output'].'/'.$this->config['file_name'].'.pdf';
                }else{
                    $file_path = $this->tmp;
                }
                
            break;
            
            default:
                $file_path = $this->tmp;
            break;
        }
        return $file_path;
    }
    /**
     * Return PDF with various options.
     * @param string $mode How two output (constants from this same class).
     * @param string $file The PDF's filename (the usage depends on $mode.
     * @return string|boolean Depending on $mode, this may be success (boolean) or PDF (string).
     */
    public function output($mode,$file){
        $file = $this->cleanFilename($file);
        switch($mode){
            case self::$PDF_DOWNLOAD:
                if(!headers_sent()){
                    header('Content-Description: File Transfer');
                    header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
                    header('Pragma: public');
                    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
                    header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
                    // force download dialog
                    header('Content-Type: application/force-download');
                    header('Content-Type: application/octet-stream', false);
                    header('Content-Type: application/download', false);
                    header('Content-Type: application/pdf', false);
                    // use the Content-Disposition header to supply a recommended filename
                    header('Content-Disposition: attachment; filename="'.basename($file).'";');
                    header('Content-Transfer-Encoding: binary');
                    header('Content-Length: '.strlen($this->pdf));
                    echo $this->pdf;
                }else{
                    throw new Exception('WKPDF download headers were already sent.');
                }
                break;
            case self::$PDF_ASSTRING:
                return $this->pdf;
                break;
            case self::$PDF_EMBEDDED:
                if(!headers_sent()){
                    header('Content-Type: application/pdf');
                    header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
                    header('Pragma: public');
                    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
                    header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
                    header('Content-Length: '.strlen($this->pdf));
                    header('Content-Disposition: inline; filename="'.basename($file).'";');
                    echo $this->pdf;
                }else{
                    throw new Exception('WKPDF embed headers were already sent.');
                }
                break;
            case self::$PDF_SAVEFILE:
                if (file_put_contents($file,$this->pdf) !== FALSE) {
                    return $file;
                } else {    
                    return FALSE;
                }    
                break;
            default:
                throw new Exception('WKPDF invalid mode "'.htmlspecialchars($mode,ENT_QUOTES).'".');
        }
        return false;
    }
    
    /**
     * Convert HTML to PDF.
     */
    public function render_path($path, $filename = ''){
        $this->get_filename();
        if (empty($this->web)) {
            //$this->web=$GLOBALS['WKPDF_BASE_SITE'].$GLOBALS['WKPDF_BASE_PATH'].'tmp/'.basename($this->tmp);
            $this->success = false;
            exit;
        }

        $filename = $this->cleanFilename($filename);
        
        $job =    '"'.$this->cmd.'"'
        .(($this->copies>1)?' --copies '.$this->copies:'')                    // number of copies
        .' --orientation '.$this->orient                                    // orientation
        .' --page-size '.$this->size                                        // page size
        .' -B 12 -T 12 -L 12 -R 12'                                            // set a 12mm border / half an inch
        .' --dpi 100'
        //.' --load-error-handling ignore '
        .($this->toc?' --toc':'')                                            // table of contents
        .($this->grayscale?' --grayscale':'')                                // grayscale
        .(($this->title!='')?' --title "'.$this->title.'"':'')                // title
        .' '.$this->web .' '. $this->tmp . ' 2>&1';                                    // URL and file to write to

        if (shell_exec($job) == null) {
            $this->status='error';
        }
        $this->pdf=file_get_contents($this->tmp);
        
        if ($filename == '') {
            copy($this->tmp, $path.'/'.$this->filename.'.pdf');
            return $path.'/'.$this->filename.'.pdf';
        } else {
            copy($this->tmp, $path.'/'.$filename);
            unlink($this->tmp);
            return $path.'/'.$filename;
        }
    }
    
    private function cleanFilename($filename) {
        if (empty($filename)) return $filename;
        
        $filename = preg_replace('/[\x00-\x1F\x80-\xFF]/', '_', $filename);
        
        return $filename;
    }
    
    /**
     * Convert HTML to PDF.
     */
    public function render_filename($path, $filename = ''){
        $this->get_filename();
        if (empty($this->web)) {
            //$this->web=$GLOBALS['WKPDF_BASE_SITE'].$GLOBALS['WKPDF_BASE_PATH'].'tmp/'.basename($this->tmp);
            $this->success = false;
            exit;
        }

        $filename = $this->cleanFilename($filename);
        
        $job =    '"'.$this->cmd.'"'
        .(($this->copies>1)?' --copies '.$this->copies:'')                    // number of copies
        .' --orientation '.$this->orient                                    // orientation
        .' --page-size '.$this->size                                        // page size
        .' -B 12 -T 12 -L 12 -R 12'                                            // set a 12mm border / half an inch
        .' --dpi 100'
        //.' --load-error-handling ignore '
        .($this->toc?' --toc':'')                                            // table of contents
        .($this->grayscale?' --grayscale':'')                                // grayscale
        .(($this->title!='')?' --title "'.$this->title.'"':'')                // title
        .' '.$this->web .' '. $this->tmp . ' 2>&1';                                    // URL and file to write to

        if (shell_exec($job) == null) {
            $this->status='error';
        }
        $this->pdf=file_get_contents($this->tmp);
        
        if ($filename == '') {
            copy($this->tmp, $path.'/'.$this->filename.'.pdf');
            return $this->filename.'.pdf';
        } else {
            copy($this->tmp, $path.'/'.$filename);
            unlink($this->tmp);
            return $filename;
        }
    }
}
?>

